package com.mall.search.sort;

import java.io.IOException;

import org.apache.lucene.index.AtomicReaderContext;
import org.apache.lucene.search.FieldCache;
import org.apache.lucene.search.FieldCache.Ints;
import org.apache.lucene.search.FieldComparator;
import org.apache.lucene.search.FieldComparatorSource;

/**
 * @author 
 * @Description 
 */
public class DistanceComparatorSource extends FieldComparatorSource{
    private long x;
    private long y;
    public DistanceComparatorSource(long x,long y){
        this.x=x;
        this.y=y;
    }
    /* (non-Javadoc)
     * @see org.apache.lucene.search.FieldComparatorSource#newComparator(java.lang.String, int, int, boolean)
     */
    @Override
    public FieldComparator<?> newComparator(String fieldName, int numHits,
            int sortPos, boolean reversed) throws IOException {
        // TODO Auto-generated method stub
        return new DistanceScoreDocLookupComparator(fieldName, numHits);
    }
    
    private class DistanceScoreDocLookupComparator extends FieldComparator{
        private Ints xDoc,yDoc;
        private float[] value;
        private float bottom;
        String fieldName;
        
        public DistanceScoreDocLookupComparator(String fidldName,int numHits){
            value=new float[numHits];
            this.fieldName=fidldName;
        }
        
        /* (non-Javadoc)
         * 传入新的AtomicReaderContext 所有的后续的docIDs都会关联到当前的reader（
         *如果您需要将其映射到一个顶级docID您必须添加docBase）
         *context 当前reader的上下文环境
         *Returns  比较器需要用到这个实例，大多数比较器都是返回当前实例，夸segment的重用当前实例
         *
         */
        @Override
        public FieldComparator setNextReader(AtomicReaderContext context)
                throws IOException {
            xDoc=FieldCache.DEFAULT.getInts(context.reader(), "x", false);
            yDoc=FieldCache.DEFAULT.getInts(context.reader(), "y", false);
            return this;
        }
    
        
        @Override
        public int compare(int slot1, int slot2) {
            if(value[slot1]<value[slot2])return -1;
            if(value[slot1]>value[slot2])return 1;
            return 0;
        }

        /* (non-Javadoc)
         * 设置 最底位置，即 进到对比队列中的最小值（排在末尾的）；
         */
        @Override
        public void setBottom(int slot) {
            bottom=value[slot];
        }

        /* (non-Javadoc)
         * 与文档进行底部比对，只有在setBottom 之后才会调用，与 compare（int,int）功能相同
         * 对于一次命中相对较多的搜索中，这个方法会成为一个调用热点。（是到目前为止调用最为频繁的一个方法）
         */
        @Override
        public int compareBottom(int doc) throws IOException {
            float docDistance=getDistance(doc);
            if(bottom<docDistance)return -1;
            if(bottom>docDistance)return 1;
            return 0;
        }

        /* (non-Javadoc)
         * 当一个命中结果具有争议性的时候会调用这个方法，你需要复制任何一个与文档相关的状态
         * 在之后会再次比对，并放入指定的位置
         */
        @Override
        public void copy(int slot, int doc) throws IOException {
            value[slot]=getDistance(doc);
        }

        public float getDistance(int doc){
        	long deltax=xDoc.get(doc)-x;
        	long deltay=yDoc.get(doc)-y;
            return (float)Math.sqrt(deltax*deltax+deltay*deltay);
        }
        
        /* (non-Javadoc)
         * 返回当前位置的实际值
         */
        @Override
        public Object value(int slot) {
            return Float.valueOf(value[slot]);
        }

		@Override
		public void setTopValue(Object value) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public int compareTop(int doc) throws IOException {
			// TODO Auto-generated method stub
			return 0;
		}

       
        
    }
}
